Completed
Push — master ( 2ba6ee...8a1088 )
by Maxence
02:21
created

nav.onError   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 2
nc 2
nop 1
1
/*
2
 * FullTextSearch - Full text search framework for Nextcloud
3
 *
4
 * This file is licensed under the Affero General Public License version 3 or
5
 * later. See the COPYING file.
6
 *
7
 * @author Maxence Lange <[email protected]>
8
 * @copyright 2018
9
 * @license GNU AGPL version 3 or any later version
10
 *
11
 * This program is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License as
13
 * published by the Free Software Foundation, either version 3 of the
14
 * License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 */
25
26
/** global: OCA */
27
/** global: api */
28
/** global: search */
29
/** global: result */
30
/** global: settings */
31
32
33
34
var curr = {
35
	providerResult: [],
36
	page: 1,
37
	lastRequest: '',
38
	lastRequestTimer: null,
39
	lastRequestTimerQueued: false,
40
	lastRequestTimerForcing: false,
41
42
	setProviderResult: function (id, value) {
43
		curr.providerResult[id] = value;
44
	},
45
46
	getProviderResult: function (id) {
47
		var current = curr.providerResult[id];
48
		if (!current) {
49
			current = [];
50
		}
51
52
		return current;
53
	}
54
55
};
56
57
58
var nav = {
59
60
		manageDivProviderNavigation: function (divProviderNavigation, request, meta) {
61
62
			var maxPage = Math.ceil(meta.total / request.size);
63
64
			divProviderNavigation.attr('data-time', meta.time);
65
			divProviderNavigation.attr('data-page', request.page);
66
			divProviderNavigation.attr('data-options', JSON.stringify(request.options));
67
			divProviderNavigation.attr('data-search', request.search);
68
			divProviderNavigation.attr('data-max-page', maxPage);
69
			divProviderNavigation.attr('data-size', request.size);
70
			divProviderNavigation.attr('data-total', meta.total);
71
72
			var providerTitle = divProviderNavigation.attr('data-provider-title');
73
			var left = "the search in " + providerTitle + " for '" + request.search + "' returned " +
74
				meta.total + " results in " + meta.time + "ms";
75
			divProviderNavigation.find('.provider_navigation_left').text(left);
76
77
			if (maxPage > 1) {
78
				divProviderNavigation.find('.provider_navigation_curr').text(request.page + ' / ' +
79
					maxPage).stop().fadeTo(200, 1);
80
81
				divProviderNavigation.find('.provider_navigation_prev').stop().fadeTo(200,
82
					(request.page > 1) ? 1 : 0);
83
				divProviderNavigation.find('.provider_navigation_next').stop().fadeTo(200,
84
					(request.page < maxPage) ? 1 : 0);
85
			} else {
86
				divProviderNavigation.find('.provider_navigation_prev').stop().fadeTo(200, 0);
87
				divProviderNavigation.find('.provider_navigation_curr').stop().fadeTo(200, 0);
88
				divProviderNavigation.find('.provider_navigation_next').stop().fadeTo(200, 0);
89
			}
90
		},
91
92
93
		manageDivProviderResult: function (divProviderResult, newResult, oldResult) {
94
			//replaceWith();
95
			nav.divProviderResultAddItems(divProviderResult, newResult, oldResult);
96
			if (oldResult) {
97
				nav.divProviderResultRemoveItems(divProviderResult, newResult, oldResult);
98
				nav.divProviderResultMoveItems(divProviderResult, newResult, oldResult);
99
			}
100
		},
101
102
103
		divProviderResultAddItems: function (divProviderResult, newResult, oldResult) {
104
105
			var precItem = null;
106
			for (var i = 0; i < newResult.length; i++) {
107
				var entry = newResult[i];
108
				if (result.getResultIndex(entry.id, oldResult) > -1) {
109
					precItem = nav.getDivResult(entry.id, divProviderResult);
110
					nav.fillDivResult(precItem, entry);
111
					continue;
112
				}
113
114
				var divResult = nav.generateDivResult(entry, nav.generateTemplateEntry(entry));
115
				if (precItem === null) {
116
					divProviderResult.prepend(divResult);
117
				} else {
118
					precItem.after(divResult);
119
				}
120
121
				divResult.slideDown(settings.delay_result, function () {
0 ignored issues
show
Bug introduced by
It is generally not recommended to make functions within a loop.

While making functions in a loop will not lead to any runtime error, the code might not behave as you expect as the variables in the scope are not imported by value, but by reference. Let’s take a look at an example:

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(function() {
        alert(i);
    });
}

funcs[0](); // alert(10);
funcs[1](); // alert(10);
/// ...
funcs[9](); // alert(10);

If you would instead like to bind the function inside the loop to the value of the variable during that specific iteration, you can create the function from another function:

var createFunc = function(i) {
    return function() {
        alert(i);
    };
};

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(createFunc(i));
}

funcs[0](); // alert(0)
funcs[1](); // alert(1)
// ...
funcs[9](); // alert(9)
Loading history...
122
					$(this).children('.result_template').fadeTo(settings.delay_result, 1);
123
				});
124
125
				precItem = divResult;
126
			}
127
128
		},
129
130
131
		divProviderResultRemoveItems: function (divProviderResult, newResult, oldResult) {
132
			for (var i = 0; i < oldResult.length; i++) {
133
				var entry = oldResult[i];
134
				if (result.getResultIndex(entry.id, newResult) === -1) {
135
					var divResult = nav.getDivResult(entry.id, divProviderResult);
136
					divResult.fadeTo(settings.delay_result, 0, function () {
0 ignored issues
show
Bug introduced by
It is generally not recommended to make functions within a loop.

While making functions in a loop will not lead to any runtime error, the code might not behave as you expect as the variables in the scope are not imported by value, but by reference. Let’s take a look at an example:

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(function() {
        alert(i);
    });
}

funcs[0](); // alert(10);
funcs[1](); // alert(10);
/// ...
funcs[9](); // alert(10);

If you would instead like to bind the function inside the loop to the value of the variable during that specific iteration, you can create the function from another function:

var createFunc = function(i) {
    return function() {
        alert(i);
    };
};

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(createFunc(i));
}

funcs[0](); // alert(0)
funcs[1](); // alert(1)
// ...
funcs[9](); // alert(9)
Loading history...
137
						$(this).slideUp(settings.delay_result, function () {
138
							$(this).remove();
139
						});
140
					});
141
				}
142
			}
143
		},
144
145
146
		divProviderResultMoveItems: function (divProviderResult, newResult, oldResult) {
147
148
			var precId = '';
149
150
			oldResult = result.recalibrateResult(oldResult, newResult);
151
			newResult = result.recalibrateResult(newResult, oldResult);
152
			for (var i = 0; i < newResult.length; i++) {
153
				var entry = newResult[i];
154
155
				var pos = result.getResultIndex(entry.id, oldResult);
156
				if (pos > -1 && pos !== i) {
157
					nav.animateMoveDivResult(entry.id, divProviderResult, precId);
158
				}
159
160
				precId = newResult[i].id;
161
			}
162
		},
163
164
165
		animateMoveDivResult: function (entryId, divProviderResult, precId) {
166
167
			var divResult = nav.getDivResult(entryId, divProviderResult);
168
169
			if (precId === '') {
170
				divResult.fadeTo(settings.delay_result, 0.35, function () {
171
					$(this).prependTo(divProviderResult).fadeTo(100, 1);
172
				});
173
			} else {
174
				var precItem = nav.getDivResult(precId, divProviderResult);
175
				divResult.fadeTo(settings.delay_result, 0.35, function () {
176
					$(this).insertAfter(precItem).fadeTo(100, 1);
177
				});
178
			}
179
180
		},
181
182
183
		getDivProvider: function (providerId, providerName) {
184
			var ret = null;
185
			settings.resultContainer.children('.provider_header').each(function () {
186
				if ($(this).attr('data-id') === providerId) {
187
					ret = $(this);
188
				}
189
			});
190
191
			if (ret === null) {
192
				ret = nav.generateDivProvider(providerId, providerName);
193
				settings.resultContainer.append(ret);
194
			}
195
196
			return ret;
197
		},
198
199
200
		getDivResult: function (resultId, divProviderResult) {
201
			var ret = null;
202
			divProviderResult.children('.result_entry').each(function () {
203
				if ($(this).attr('data-id') === resultId) {
204
					ret = $(this);
205
				}
206
			});
207
208
			return ret;
209
		},
210
211
212
		fillDivResult: function (divResult, entry) {
213
			divResult.find('#title').text(entry.title);
214
215
			divResult.find('#source').html('&nbsp;');
216
			if (entry.info.source !== '') {
217
				divResult.find('#source').text(entry.info.source);
218
			}
219
220
			if (settings.options.show_hash === '1') {
221
				divResult.find('#source').text(entry.hash);
222
			}
223
224
			nav.fillDivResultExcepts(divResult, entry);
225
226
			if (entry.link !== '') {
227
				divResult.on('click', function () {
228
					window.open(entry.link, '_self');
229
				});
230
				divResult.find('div').each(function () {
231
					$(this).css('cursor', 'pointer');
232
				});
233
			}
234
		},
235
236
237
		/**
238
		 * @namespace entry.excerpts
239
		 */
240
		fillDivResultExcepts: function (divResult, entry) {
241
			if (entry.excerpts === null) {
242
				return;
243
			}
244
245
			if (entry.excerpts.length > 0) {
246
				divResult.find('#line1').text(entry.excerpts[0]);
247
			}
248
249
			if (entry.excerpts.length > 1) {
250
				divResult.find('#line2').text(entry.excerpts[1]);
251
			}
252
253
		},
254
255
		onEntryGenerated: function (divResult) {
256
257
			nav.deleteEmptyDiv(divResult, '#line1');
258
			nav.deleteEmptyDiv(divResult, '#line2');
259
260
			if (settings.parentHasMethod('onEntryGenerated')) {
261
				settings.parent.onEntryGenerated(divResult);
262
			}
263
		},
264
265
		onSearchRequest: function (data) {
266
			if (settings.parentHasMethod('onSearchRequest')) {
267
				settings.parent.onSearchRequest(data);
268
			}
269
		},
270
271
		onSearchReset: function () {
272
			if (settings.parentHasMethod('onSearchReset')) {
273
				settings.parent.onSearchReset();
274
			}
275
		},
276
277
		onResultDisplayed: function (data) {
278
			if (settings.parentHasMethod('onResultDisplayed')) {
279
				settings.parent.onResultDisplayed(data);
280
			}
281
		},
282
283
		onResultClose: function () {
284
			if (settings.parentHasMethod('onResultClose')) {
285
				settings.parent.onResultClose();
286
			}
287
		},
288
289
		onError: function (data) {
290
			if (settings.parentHasMethod('onError')) {
291
				settings.parent.onError(data);
292
			}
293
		},
294
295
		deleteEmptyDiv: function (entry, divId) {
296
			var div = entry.find(divId);
297
			if (div.text() === '') {
298
				div.remove();
299
			}
300
		},
301
302
303
		generateTemplateEntry: function (document) {
0 ignored issues
show
Unused Code introduced by
The parameter document is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
304
			var divTemplate = settings.entryTemplate;
305
			if (divTemplate === null) {
306
				divTemplate = settings.generateDefaultTemplate();
307
			}
308
309
			if (!divTemplate.length) {
310
				console.log('FullTextSearch Error: template_entry is not defined');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
311
				return;
312
			}
313
314
			var tmpl = divTemplate.html();
315
//			tmpl = tmpl.replace(/%%id%%/g, escapeHTML(document.id));
316
317
			var div = $('<div>', {class: 'result_template'});
318
			div.html(tmpl).fadeTo(0);
319
320
			return div;
321
		},
322
323
324
		generateDivResult: function (entry, divResultContent) {
325
			var divResult = $('<div>', {class: 'result_entry'});
326
327
			divResult.hide();
328
			divResult.attr('data-id', entry.id);
329
			divResult.attr('data-link', entry.link);
330
			divResult.attr('data-source', entry.source);
331
			divResult.attr('data-info', JSON.stringify(entry.info));
332
			divResult.attr('data-result', JSON.stringify(entry));
333
			divResult.append(divResultContent);
334
335
			nav.fillDivResult(divResult, entry);
336
337
			return divResult;
338
		},
339
340
341
		generateDivProvider: function (providerId, providerName) {
342
343
			var divProviderNavigation = $('<div>', {class: 'provider_navigation'});
344
			divProviderNavigation.attr('data-provider-id', providerId);
345
			divProviderNavigation.attr('data-provider-title', providerName);
346
			divProviderNavigation.append($('<div>', {class: 'provider_navigation_left'}));
347
348
			var divProviderPagination = $('<div>', {class: 'provider_navigation_right'});
349
			var divProviderPaginationPrev = $('<div>', {class: 'provider_navigation_prev'}).append(
350
				$('<div>', {class: 'provider_navigation_page'}).text('previous page'));
351
352
			divProviderPaginationPrev.on('click', function () {
353
				var prevPage = Number(divProviderNavigation.attr('data-page')) - 1;
354
				if (prevPage < 1) {
355
					return;
356
				}
357
358
				fullTextSearch.search({
0 ignored issues
show
Bug introduced by
The variable fullTextSearch seems to be never declared. If this is a global, consider adding a /** global: fullTextSearch */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
359
					providers: providerId,
360
					options: JSON.parse(divProviderNavigation.attr('data-options')),
361
					search: divProviderNavigation.attr('data-search'),
362
					page: prevPage,
363
					size: divProviderNavigation.attr('data-size')
364
				});
365
			});
366
			divProviderPagination.append(divProviderPaginationPrev);
367
368
			divProviderPagination.append($('<div>', {class: 'provider_navigation_curr'}));
369
370
			var divProviderPaginationNext = $('<div>',
371
				{class: 'provider_navigation_next'}).append(
372
				$('<div>', {class: 'provider_navigation_page'}).text('next page'));
373
374
			divProviderPaginationNext.on('click', function () {
375
				var nextPage = Number(divProviderNavigation.attr('data-page')) + 1;
376
				if (nextPage > Number(divProviderNavigation.attr('data-max-page'))) {
377
					return;
378
				}
379
380
				fullTextSearch.search({
0 ignored issues
show
Bug introduced by
The variable fullTextSearch seems to be never declared. If this is a global, consider adding a /** global: fullTextSearch */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
381
					providers: providerId,
382
					options: JSON.parse(divProviderNavigation.attr('data-options')),
383
					search: divProviderNavigation.attr('data-search'),
384
					page: nextPage,
385
					size: divProviderNavigation.attr('data-size')
386
				});
387
			});
388
			divProviderPagination.append(divProviderPaginationNext);
389
390
			if (settings.searchProviderId !== '') {
391
				var divProviderPaginationClose = $('<div>',
392
					{class: 'icon-close provider_navigation_close'});
393
				divProviderPaginationClose.on('click', function () {
394
					nav.onResultClose();
395
				});
396
				divProviderPagination.append(divProviderPaginationClose);
397
			}
398
399
400
			divProviderNavigation.append(divProviderPagination);
401
402
			var divProviderResult = $('<div>', {class: 'provider_result'});
403
404
			var divProvider = $('<div>', {class: 'provider_header'});
405
			divProvider.hide();
406
			divProvider.attr('data-id', providerId);
407
			divProvider.append(divProviderNavigation);
408
			divProvider.append(divProviderResult);
409
410
			return divProvider;
411
		}
412
413
	}
414
;
415